package com.shawny.model;

import com.shawny.GameController;

import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by Shawn Wong on 2017/3/30.
 * Try you best !
 */
public class Game {

    private enum Status {
        WAITING, COUNTING_DOWN, RUNNING, FINISHED
    }

    private Status status;
    private Map<String,Player> players;
    private GameController controller;

    public void setController(GameController controller){
        this.controller = controller;
    }


    public Game(){
        this.status = Status.WAITING;
        this.players = new ConcurrentHashMap<>();
    }

    public void join(Action joinAction){
        if(status == Status.FINISHED){
            players.clear();
            this.status = Status.WAITING;
        }

        if(players.containsKey(joinAction.getPlayerId())){
            controller.sendToUser( new Notification("normal","You already joined"));
        }


        if(players.size()>=2){
            controller.sendToUser( new Notification("normal","Not the time, Maybe later?"));
        }

        players.put(joinAction.getPlayerId(),new Player(joinAction.getPlayerId()));
        controller.sendToUser( new Notification("yourId","joined",joinAction.getPlayerId()));

        if(players.size()==2){

            controller.broadcast( new Notification("ready"," 2 Players joined ,GET READY!!!!"));
        }else if(players.size()==1){

            controller.broadcast( new Notification("normal"," 1 Players joined ,wait for another"));
        }

    }

    public void setReady(Action setReadyAction){

        players.get(setReadyAction.getPlayerId()).ready();
        controller.sendToUser(new Notification("isReady","YOU ARE READY!!!!",setReadyAction.getPlayerId()));

        if(isWaiting() && allReady()){
            setCountingDown();
        }

    }

    private void setCountingDown() {
        status = Status.COUNTING_DOWN;
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    controller.broadcast(new Notification("normal","3"));
                    Thread.sleep(1000);
                    controller.broadcast(new Notification("normal","2"));
                    Thread.sleep(1000);
                    controller.broadcast(new Notification("normal","1"));
                    Thread.sleep(1000);
                    status = Status.RUNNING;
                    controller.broadcast(new Notification("GO","GO!!!"));
                    for(int i = 9; i>=0 ;i --) {
                        Thread.sleep(1000);
                        controller.broadcast(new Notification("normal",String.valueOf(i)));

                    }
                    finishGame( );
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }


        };
        new Thread(r).start();

    }

    private void finishGame(){
        status = Status.FINISHED;
        broadCastScores();


    }

    private void broadCastScores() {

        Player winner =
            Collections.max(players.values(), (o1, o2) -> {return o1.getScore()-o2.getScore();});
        Player loser =
                Collections.min(players.values(), (o1, o2) -> {return o1.getScore()-o2.getScore();});

        StringBuilder scores = new StringBuilder();
        scores.append("胜者共出招").append(winner.getScore()).append("次.");
        scores.append("败者共出招").append(loser.getScore()).append("次.");
        scores.append(comment(winner.getScore()-loser.getScore()));
        scores.append("胜利者当然是");

        controller.broadcast( new Notification("result",scores.toString(),winner.getId()));

    }

    public String comment(int ahead){
        if(ahead <3){
            return   "真是起鼓相当的比试啊.";
        }else if(ahead <6){
            return "轻松的胜利.";
        }else if(ahead <9){
            return  "失败者真是自取其辱.";
        }else{
            return "胜者只用一根鼻毛就战胜了对手.";
        }



    }

    public void onClick(Action clickAction){

        if(status!=Status.RUNNING){
            return;
        }else if(!players.containsKey(clickAction.getPlayerId())){
            return;
        }else{
            players.get(clickAction.getPlayerId()).incrementScore();
            controller.broadcast( new Notification("increment","random move",clickAction.getPlayerId()));
        }

    }

    private boolean allReady() {
        if(players.size() < 2){
            return false;
        }else{
            for(Player p : players.values()){
                if(!p.isReady()){
                    return false;
                }
            }
            return  true;

        }

    }


    public boolean isWaiting() {
        return this.status == Status.WAITING;
    }



    public boolean isCountingDown() {
        return this.status == Status.COUNTING_DOWN;
    }

    public boolean isRunning() {
        return this.status == Status.RUNNING;
    }

    public boolean isFinished() {
        return this.status == Status.FINISHED;
    }

}
